#!/bin/bash
#
##############################################################################
#                                                                            #
#                         Pi-Star DAPNET API Tool                            #
#                                                                            #
#     Version 2.1, Code, Design and Development by Andy Taylor (MW0MWZ).     #
#       Helpfull input from Florian Wolters (DF2FET) - Thank you Flo.        #
#                                                                            #
##############################################################################
#
if [ "$(id -u)" != "0" ]; then
  echo -e "You need to be root to run this command...\n"
  exit 1
fi

# Get the stored DAPNET API Config
DAPNETAPIFile=/etc/dapnetapi.key
if [ -f ${DAPNETAPIFile} ]; then
	source <(grep = <(grep -A5 '\[DAPNETAPI\]' $DAPNETAPIFile | tr -d ' ' | tr -d '\r'))
else
	echo "Unable to find your DAPNET API Info, no API commands available."
	exit 1
fi

# Check command line arguments
if [ $# -lt 2 ]; then
	echo ""
        echo "To use this script, call the script with some arguments;"
	echo ""
	echo "Example:"
	echo "  pistar-dapnetapi M1ABC[,callsign...] \"Test Message\" [options]"
	echo ""
	echo "The above command will send a page containing \"Text Message\" to M1ABC"
	echo "More than one call can be specified for multiple recipients, separated"
	echo "by a comma, without any space in betweeen."
	echo ""
	echo "For additional feedback add the \"debug\" option:"
	echo "pistar-dapnetapi M1ABC \"Test Message\" debug"
	echo ""
	echo "Suppress the hostname with the \"nohost\" option:"
	echo "pistar-dapnetapi M1ABC \"Test Message\" nohost"
	echo ""

	exit 0
fi

# Check some options
if [ "${3^^}" = "DEBUG" ] || [ "${4^^}" = "DEBUG" ]; then
	DEBUG="1"
else
	DEBUG="0"
fi

if [ "${3^^}" = "NOHOST" ] || [ "${4^^}" = "NOHOST" ]; then
	HOST=${USER^^}
else
	HOST=$(hostname)
fi

# Setup some variables
APIURL="https://hampager.de/api"
RECIPIENT=$(echo "$1" | sed -r 's/\,/"\,"/g')
MESSAGE=${2}
SIZEHOST=${#HOST}
SIZEMESSAGE=$(expr 78 - ${SIZEHOST})
SIZETEXT=${#MESSAGE}
NUMMESSAGES=$(expr ${SIZETEXT} / ${SIZEMESSAGE})

# Curl error codes
curlErrorCodes[1]="Unsupported protocol. This build of curl has no support for this protocol."
curlErrorCodes[2]="Failed to initialize."
curlErrorCodes[3]="URL malformed. The syntax was not correct."
curlErrorCodes[4]="A feature or option that was needed to perform the desired request was not enabled or was explicitly disabled at build-time. To make curl able to do this, you probably need another build of libcurl!"
curlErrorCodes[5]="Couldn't resolve proxy. The given proxy host could not be resolved."
curlErrorCodes[6]="Couldn't resolve host. The given remote host was not resolved."
curlErrorCodes[7]="Failed to connect to host."
curlErrorCodes[22]="HTTP page not retrieved. The requested url was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if -f, --fail is used."
curlErrorCodes[23]="Write error. Curl couldn't write data to a local filesystem or similar."
curlErrorCodes[26]="Read error. Various reading problems."
curlErrorCodes[27]="Out of memory. A memory allocation request failed."
curlErrorCodes[28]="Operation timeout. The specified time-out period was reached according to the conditions."
curlErrorCodes[33]="HTTP range error. The range \"command\" didn't work."
curlErrorCodes[34]="HTTP post error. Internal post-request generation error."
curlErrorCodes[35]="SSL connect error. The SSL handshaking failed."
curlErrorCodes[37]="FILE couldn't read file. Failed to open the file. Permissions?"
curlErrorCodes[42]="Aborted by callback. An application told curl to abort the operation."
curlErrorCodes[43]="Internal error. A function was called with a bad parameter."
curlErrorCodes[45]="Interface error. A specified outgoing interface could not be used."
curlErrorCodes[47]="Too many redirects. When following redirects, curl hit the maximum amount."
curlErrorCodes[48]="Unknown option specified to libcurl. This indicates that you passed a weird option to curl that was passed on to libcurl and rejected. Read up in the manual!"
curlErrorCodes[51]="The peer's SSL certificate or SSH MD5 fingerprint was not OK."
curlErrorCodes[52]="The server didn't reply anything, which here is considered an error."
curlErrorCodes[53]="SSL crypto engine not found."
curlErrorCodes[54]="Cannot set SSL crypto engine as default."
curlErrorCodes[55]="Failed sending network data."
curlErrorCodes[56]="Failure in receiving network data."
curlErrorCodes[58]="Problem with the local certificate."
curlErrorCodes[59]="Couldn't use specified SSL cipher."
curlErrorCodes[60]="Peer certificate cannot be authenticated with known CA certificates."
curlErrorCodes[61]="Unrecognized transfer encoding."
curlErrorCodes[63]="Maximum file size exceeded."
curlErrorCodes[65]="Sending the data requires a rewind that failed."
curlErrorCodes[66]="Failed to initialise SSL Engine."
curlErrorCodes[67]="The user name, password, or similar was not accepted and curl failed to log in."
curlErrorCodes[75]="Character conversion failed."
curlErrorCodes[76]="Character conversion functions required."
curlErrorCodes[77]="Problem with reading the SSL CA cert (path? access rights?)."
curlErrorCodes[78]="The resource referenced in the URL does not exist."
curlErrorCodes[79]="An unspecified error occurred during the SSH session."
curlErrorCodes[80]="Failed to shut down the SSL connection."
curlErrorCodes[82]="Could not load CRL file, missing or wrong format (added in 7.19.0)."
curlErrorCodes[83]="Issuer check failed (added in 7.19.0)."
curlErrorCodes[85]="RTSP: mismatch of CSeq numbers"
curlErrorCodes[86]="RTSP: mismatch of Session Identifiers"
curlErrorCodes[89]="No connection available, the session will be queued"


# Function that parse returned JSON for error code
function python_ParseJSON() {
	DAPNET_RESULT_ARG="$1" python  - <<EOF
import os
import json
import sys

jdata = os.environ['DAPNET_RESULT_ARG']
data = json.loads(jdata)

if 'code' in data:
    print("%s [error:%d]" %  (str(data["message"]), data["code"]))
    sys.exit(1)
else:
    sys.exit(0)
EOF
}

# Function that send a page
# returns 0 on success, otherwise 1
function send_page () {
	# Set the variables for the function
	TEXT="$(echo ${1})"

	# Debug option
	if [ "${DEBUG}" -gt "0" ]; then
	        echo " Request to DAPNET API: {"
	        echo "  \"text\": \"${HOST^^}: ${TEXT}\","
	        echo "  \"callSignNames\": ["
	        echo "    \"${RECIPIENT}\""
	        echo "  ],"
	        echo "  \"transmitterGroupNames\": ["
	        echo "    \"${TRXAREA}\""
	        echo "  ],"
	        echo "  \"emergency\": false"
	        echo "}"
	        echo ""
	        echo ""
	fi

	# Speak to DAPNET
	RESULT=$(curl -f -S -s -H "Content-Type: application/json" -X POST -u ${USER}:${PASS} -d \
	        "{ \"text\": \"${HOST^^}: ${TEXT}\", \"callSignNames\": [\"${RECIPIENT}\"], \"transmitterGroupNames\": [\"${TRXAREA}\"], \"emergency\": false }" \
	        ${APIURL}/calls 2>&1)
	ret=$?

	# Check curl return code
	if [ "$ret" != "0" ]; then
		echo "ERROR: ($ret) ${curlErrorCodes[ret]}"
		return $ret
	fi

	# Debug option
	if [ "${DEBUG}" -gt "0" ]; then
	        echo "Answer from DAPNET API: '${RESULT}'"
	        echo ""
	        echo ""
	fi

	# Parse returned JSON code, to catch possible error
	error=$(python_ParseJSON "${RESULT}")
	ret=$?

	if [ "$ret" != "0" ]; then
		echo "$error"
	fi

	return $ret
}


if [ "${NUMMESSAGES}" -gt "0" ]; then
	# OK now I know I need to split the message, now I need to know now many I need.
	SIZEMESSAGESPLIT=$(expr 73 - ${SIZEHOST})
	NUMMESSAGESSPLIT=$(expr ${SIZETEXT} / ${SIZEMESSAGESPLIT} + 1)

	# Limit output to 5 concurrent messages
	if [ "${NUMMESSAGESSPLIT}" -ge "6" ]; then
		NUMMESSAGESSPLIT=5
	fi

	# Now I need to split the message into ${NUMMESSAGESSPLIT} chunks
	COUNTER=1
	while [ ${COUNTER} -le ${NUMMESSAGESSPLIT} ]; do
		TXTSTART=$(expr ${SIZEMESSAGESPLIT} \* ${COUNTER} - ${SIZEMESSAGESPLIT})
		TXTPRE="${COUNTER}/${NUMMESSAGESSPLIT}"
		TXTCHUNK=${MESSAGE:$TXTSTART:$SIZEMESSAGESPLIT}
		TXTMESSAGE=${TXTPRE}" "${TXTCHUNK}

		send_page "${TXTMESSAGE}"
		ret=$?

		if [ "$ret" != "0" ]; then
		    exit $ret
		fi

		let COUNTER=COUNTER+1
	done
else
	# Messge does not need to be split
	send_page "${MESSAGE}"
	ret=$?
	 
	if [ "$ret" != "0" ]; then
	    exit $ret
	fi
fi

echo "Page to \"$RECIPIENT\" successfully sent."

# Exit Clean
exit 0
